package com.guide.router;

import java.util.regex.Pattern;

public class ConsistentHashRouter extends DBRouter {

	private final int CIRCLE_LENGTH = 16;
	private int[] circleNodes = new int[CIRCLE_LENGTH];
	private int shardCount;
	
	public ConsistentHashRouter(){
		
	}
	
	@Override
	public int getShardingIndex(long shardingId, int shardCount) {

		if(this.shardCount != shardCount) {
			throw new IllegalAccessError("shard count not matches the weights setting");
		}
		return circleNodes[(int)(shardingId % CIRCLE_LENGTH)];
	}

	@Override
	public int getTableIndex(long shardingId, int cellCount) {
		return cellCount > 1 ? (int)(shardingId % cellCount) : -1;
	}


	public void setWeights(String weights) {
		if(weights == null
				|| "".equals(weights)
				|| !Pattern.matches("^\\d+(,\\d+)*$", weights)) {
			throw new IllegalArgumentException(" weights string must matches the format: 5[,5,55]");
		}
		
		String[] weightsArr = weights.split("\\,");
		int sum = 0;
		int curIndex = CIRCLE_LENGTH - 1;
		
		for(int i = weightsArr.length - 1; i >= 0; i--) {
			int weight = Integer.parseInt(weightsArr[i]);
			sum += weight;
			for(int j = 0; j < weight; j++) {
				// 虚拟环上的这端弧线上�?��节点都指向真实数据结�?i�?
				circleNodes[curIndex--] = i;
			}
			
		}
		
		if(sum != CIRCLE_LENGTH) {
			throw new IllegalArgumentException("The sum of all weights must equals to " + CIRCLE_LENGTH);
		}
		
		this.shardCount = weightsArr.length;
		
	}
	
	public int[] getCircleNodes(){
		return circleNodes;
	}
	
	public static void main(String[] args) {
		ConsistentHashRouter cr = new ConsistentHashRouter();
		cr.setWeights("4,4,4,2,2");
		for (int k=0;k<cr.getCircleNodes().length;k++) {
			System.out.print(cr.getCircleNodes()[k]);System.out.print(",");
		}
		System.out.println("--------------------");
		System.out.println(cr.getShardingIndex(2888249, 4));
		System.out.println(2888249%16);
	}

}
